package concursos.controladores;

import java.io.IOException;
import java.util.ArrayList;
import java.util.Date;
import java.util.List;
import java.util.Properties;

import javax.ejb.EJB;
import javax.faces.application.FacesMessage;
import javax.faces.bean.ManagedBean;
import javax.faces.bean.ManagedProperty;
import javax.faces.bean.SessionScoped;
import javax.faces.context.FacesContext;
import javax.mail.Message;
import javax.mail.MessagingException;
import javax.mail.PasswordAuthentication;
import javax.mail.Session;
import javax.mail.Transport;
import javax.mail.internet.InternetAddress;
import javax.mail.internet.MimeMessage;

import org.jboss.crypto.CryptoUtil;

import concursos.interfaces.ArquivoService;
import concursos.interfaces.LembreteService;
import concursos.interfaces.LoginService;
import concursos.interfaces.UsuarioService;
import concursos.modelos.TipoArquivo;
import concursos.modelos.Usuario;

@ManagedBean
@SessionScoped
public class UsuarioMB {

	@EJB
	private UsuarioService beanUsuario;
	@EJB
	private LoginService loginEjb;
	@EJB
	private LembreteService lembreteEjb;
	@EJB
	private ArquivoService arquivoEjb;
	private Usuario usuario = new Usuario();
	private Usuario novoUsuario = new Usuario();
	private String verificacaoSenha;
	private int idBusca, idExclusao;
	private List<Usuario> listaUsuarios = new ArrayList<Usuario>();
	private String username = "", senha = "", codigoAutorizar = "";
	private String novaSenha;
	@ManagedProperty(value = "#{concursoMB}")
	private ConcursoMB concursoMb;
	private Date dataNascimento;
	private int quantidadeLembretesAtual;

	public UsuarioMB() {
	}

	public String getCodigoAutorizar() {
		return this.codigoAutorizar;
	}

	public void setCodigoAutorizar(String codigoAutorizar) {
		this.codigoAutorizar = codigoAutorizar;
	}

	public String getUsername() {
		return this.username;
	}

	public void setUsername(String username) {
		this.username = username;
	}

	public String getSenha() {
		return this.senha;
	}

	public void setSenha(String senha) {
		this.senha = senha;
	}

	public void cadastrarUsuario() throws IOException {
		Date data = new Date();

		FacesContext context = FacesContext.getCurrentInstance();
		context.getExternalContext().getFlash().setKeepMessages(true);

		if (this.verificarSenhas()) {
			try {
				if (this.dataNascimento.after(data)) {
					context.addMessage(null, new FacesMessage("Erro",
							"Data de nascimento inválida"));
				} else {
					this.cadastrar();
				}

			} catch (NullPointerException e) {
				this.cadastrar();
			} catch (Exception exception) {
				context.addMessage(null, new FacesMessage("Erro",
						"CPF ja cadastrado"));
			}
		} else {
			context.addMessage(null, new FacesMessage("Erro",
					"As senhas não conferem"));
		}
	}

	private void cadastrar() throws IOException {
		FacesContext context = FacesContext.getCurrentInstance();

		this.novoUsuario.setDataNascimento(this.dataNascimento);
		try {
			this.novoUsuario = this.beanUsuario.cadastrarUsuario(novoUsuario);
		} catch (Exception exception) {
			context.addMessage(null, new FacesMessage("Erro",
					"Este usuário ja existe. Escolha outro nome."));
		}

		TipoArquivo t = new TipoArquivo("Edital", this.novoUsuario);
		this.arquivoEjb.adicionarTipoArquivo(t);
		TipoArquivo t2 = new TipoArquivo("Retificações", this.novoUsuario);
		this.arquivoEjb.adicionarTipoArquivo(t2);

		this.usuario = novoUsuario;
		this.novoUsuario = new Usuario();
		FacesContext.getCurrentInstance().getExternalContext().getSessionMap()
				.put("usuario", this.novoUsuario);

		FacesContext.getCurrentInstance().getExternalContext()
				.redirect("../user/listarConcursos.xhtml");
	}

	public void urlCadUsuario() throws IOException {
		FacesContext.getCurrentInstance().getExternalContext()
				.redirect("publico/cadastrarUsuario.xhtml");
	}

	public void urlCadUsuario2() throws IOException {
		FacesContext.getCurrentInstance().getExternalContext()
				.redirect("cadastrarUsuario.xhtml");
	}

	public void atualizarUsuario() {
		this.usuario = this.beanUsuario.cadastrarUsuario(usuario);

		FacesContext.getCurrentInstance().getExternalContext().getSessionMap()
				.put("usuario", this.usuario);

		FacesContext context = FacesContext.getCurrentInstance();
		context.addMessage(null, new FacesMessage("Sucesso",
				"Usuario atualizado com sucesso"));
	}

	private boolean verificarSenhas() {
		if (this.novoUsuario.getSenha().equalsIgnoreCase(this.verificacaoSenha))
			return true;
		return false;
	}

	public void alterarSenha() {

		// Verificando se senha atual confere
		String hashAtual = this.usuario.getSecString();
		String senhaBanco = this.usuario.getSenha();

		String hash = CryptoUtil.createPasswordHash("MD5", "hex", null, null,
				this.senha.concat(hashAtual));

		if (!hash.equals(senhaBanco)) {
			FacesContext context = FacesContext.getCurrentInstance();
			context.addMessage(null, new FacesMessage(
					FacesMessage.SEVERITY_ERROR, "Senha atual inv�lida", null));
		} else {
			// setando a nova senha
			this.usuario.setSenha(this.novaSenha);
			this.usuario = this.beanUsuario.alterarSenha(usuario);

			FacesContext.getCurrentInstance().getExternalContext()
					.getSessionMap().put("usuario", this.usuario);

			FacesContext context = FacesContext.getCurrentInstance();
			context.addMessage(null, new FacesMessage(
					"Senha alterada com sucesso", null));
		}
	}

	public void alterarSenhaPerdida() throws IOException {
		FacesContext context = FacesContext.getCurrentInstance();
		try {
			this.usuario = this.beanUsuario
					.buscarPorCodigoAutorizacao(this.codigoAutorizar);
		} catch (Exception exception) {
		}

		if (this.usuario != null) {
			this.usuario.setSenha(this.novaSenha);
			this.usuario.setCodigoAutorizacao(this.gerarSenhaAleatoria());
			this.usuario = this.beanUsuario.alterarSenha(usuario);

			FacesContext.getCurrentInstance().getExternalContext()
					.getSessionMap().put("usuario", this.usuario);
			FacesContext.getCurrentInstance().getExternalContext()
					.redirect("../user/listarConcursos.xhtml");
		} else
			context.addMessage(null, new FacesMessage(
					FacesMessage.SEVERITY_ERROR, "Invalido", "Codigo invalido"));

	}

	public Usuario getUsuario() {
		return this.usuario;
	}

	public void setUsuario(Usuario usuario) {
		this.usuario = usuario;
	}

	public List<Usuario> getUsuarios() {
		return new ArrayList<Usuario>(this.beanUsuario.listarUsuarios());
	}

	public UsuarioService getBeanUsuario() {
		return beanUsuario;
	}

	public void setBeanUsuario(UsuarioService beanUsuario) {
		this.beanUsuario = beanUsuario;
	}

	public String getVerificacaoSenha() {
		return verificacaoSenha;
	}

	public void setVerificacaoSenha(String verificaoSenha) {
		this.verificacaoSenha = verificaoSenha;
	}

	public void excluirUsuario() {
		this.beanUsuario.excluirUsuario(this.idExclusao);
	}

	public List<Usuario> listarUsuarios() {
		this.listaUsuarios = this.beanUsuario.listarUsuarios();
		return this.listaUsuarios;
	}

	public void buscaPorId() {
		this.usuario = this.beanUsuario.buscaPorId(idBusca);
		this.listaUsuarios.add(this.usuario);
	}

	public int getIdBusca() {
		return this.idBusca;
	}

	public void setIdBusca(int idBusca) {
		this.idBusca = idBusca;
	}

	public int getIdExclusao() {
		return this.idExclusao;
	}

	public void setIdExclusao(int idExclusao) {
		this.idExclusao = idExclusao;
	}

	public List<Usuario> getListaUsuarios() {
		return this.listaUsuarios;
	}

	public void setListaUsuarios(List<Usuario> listaUsuarios) {
		this.listaUsuarios = listaUsuarios;
	}

	public String login() throws IOException {
		try {
			this.usuario = this.loginEjb.login(this.username, this.senha);
			System.out.println("Entrando no sistema... Usuario: "
					+ this.usuario.getNomeUsuario());
			FacesContext.getCurrentInstance().getExternalContext()
					.getSessionMap().put("usuario", this.usuario);

			this.quantidadeLembretesAtual = this.lembreteEjb
					.quantidadeLembretesDataAtual(this.usuario.getId());

			this.concursoMb.setUsuario(this.usuario);
			this.concursoMb.setId_usuario(this.usuario.getId());
			this.concursoMb.setFiltroBusca("Novos");

			// carrega os concursos novos ao logar
			this.concursoMb.setListaConcursos(this.concursoMb.getBeanConcurso()
					.listarConcursosNovos(this.concursoMb.getId_usuario()));

			FacesContext.getCurrentInstance().getExternalContext()
					.redirect("../user/listarConcursos.xhtml");
			return null;

		} catch (NullPointerException exception) {
			FacesContext context = FacesContext.getCurrentInstance();
			context.addMessage(null, new FacesMessage(
					FacesMessage.SEVERITY_ERROR, "Erro",
					"Login ou senha inválidos"));
			this.username = "";
			return null;
		}
	}

	public String logout() {
		System.out.println("Saindo do sistema... Usuario: "
				+ this.usuario.getNomeUsuario());
		FacesContext.getCurrentInstance().getExternalContext().getSessionMap()
				.clear();
		this.usuario = new Usuario();
		try {
			FacesContext.getCurrentInstance().getExternalContext()
					.redirect("/PDSConcursosWeb/");
		} catch (IOException exception) {
		}
		return "";
	}

	private String gerarSenhaAleatoria() {
		String[] carct = { "0", "1", "2", "3", "4", "5", "6", "7", "8", "9",
				"a", "b", "c", "d", "e", "f", "g", "h", "i", "j", "k", "l",
				"m", "n", "o", "p", "q", "r", "s", "t", "u", "v", "w", "x",
				"y", "z", "A", "B", "C", "D", "E", "F", "G", "H", "I", "J",
				"K", "L", "M", "N", "O", "P", "Q", "R", "S", "T", "U", "V",
				"W", "X", "Y", "Z" };

		String senha = "";

		for (int x = 0; x < 10; x++) {
			int j = (int) (Math.random() * carct.length);
			senha += carct[j];
		}

		return senha;
	}

	public void recuperarSenha() {
		String codigoAleatorio = this.gerarSenhaAleatoria();

		if (this.username.equals("")) {
			FacesContext context = FacesContext.getCurrentInstance();
			context.addMessage(null, new FacesMessage("Invalido",
					"Informe o nome de usuario"));

		} else {
			try {
				this.usuario = this.beanUsuario.buscaPorUsername(this.username);
				String msg = "Seu codigo de recuperacao eh: " + codigoAleatorio
						+ "\nUtilize-o para alterar sua senha.";

				this.usuario.setCodigoAutorizacao(codigoAleatorio);
				this.beanUsuario.cadastrarUsuario(this.usuario);

				try {
					this.enviarEmail(this.usuario, msg);
					FacesContext context = FacesContext.getCurrentInstance();
					context.addMessage(
							null,
							new FacesMessage(FacesMessage.SEVERITY_INFO,
									"Aviso",
									"Um email com seu c�digo de verifica��o foi enviado para seu email"));
				} catch (MessagingException exception) {
					System.out
							.println("Erro ao enviar email de recuperar senha...");
					FacesContext context = FacesContext.getCurrentInstance();
					context.addMessage(
							null,
							new FacesMessage(FacesMessage.SEVERITY_FATAL,
									"Erro",
									"Ocorreu um erro ao enviar o email verifique sua conex�o"));
				}
			} catch (Exception exception) {
				FacesContext context = FacesContext.getCurrentInstance();
				context.addMessage(null, new FacesMessage("Invalido",
						"Usuario inexistente"));
			}

		}
	}

	private void enviarEmail(Usuario usuario, String msg)
			throws MessagingException {
		System.out.println("Enviando email...");
		Properties props = new Properties();
		props.put("mail.smtp.host", "smtp.gmail.com");
		props.put("mail.smtp.socketFactory.port", "465");
		props.put("mail.smtp.socketFactory.class",
				"javax.net.ssl.SSLSocketFactory");
		props.put("mail.smtp.auth", "true");
		props.put("mail.smtp.port", "465");

		Session session = Session.getInstance(props,
				new javax.mail.Authenticator() {
					protected PasswordAuthentication getPasswordAuthentication() {
						return new PasswordAuthentication(
								"meusconcursospdsc@gmail.com", "meusconcursos");
					}
				});
		try {

			Message message = new MimeMessage(session);
			message.setFrom(new InternetAddress("meusconcursospdsc@gmail.com"));

			message.setRecipients(Message.RecipientType.TO,
					InternetAddress.parse(usuario.getEmail()));
			message.setSubject("Meus Concursos - Recuperar Senha");
			message.setText(msg);

			Transport.send(message);
			System.out.println("Email de senha enviado para: "
					+ usuario.getEmail());
		} catch (MessagingException e) {
			throw new MessagingException("Erro ao enviar e-mail");
		}

		this.usuario = new Usuario();
	}

	public Usuario getNovoUsuario() {
		return novoUsuario;
	}

	public void setNovoUsuario(Usuario novoUsuario) {
		this.novoUsuario = novoUsuario;
	}

	public String getNovaSenha() {
		return novaSenha;
	}

	public void setNovaSenha(String novaSenha) {
		this.novaSenha = novaSenha;
	}

	public ConcursoMB getConcursoMb() {
		return this.concursoMb;
	}

	public void setConcursoMb(ConcursoMB concursoMb) {
		this.concursoMb = concursoMb;
	}

	public Date getDataNascimento() {
		return this.dataNascimento;
	}

	public void setDataNascimento(Date dataNascimento) {
		this.dataNascimento = dataNascimento;
	}

	public int getQuantidadeLembretesAtual() {
		return this.quantidadeLembretesAtual;
	}

	public void setQuantidadeLembretesAtual(int quantidadeLembretesAtual) {
		this.quantidadeLembretesAtual = quantidadeLembretesAtual;
	}

	public LembreteService getLembreteEjb() {
		return this.lembreteEjb;
	}

	public void setLembreteEjb(LembreteService lembreteEjb) {
		this.lembreteEjb = lembreteEjb;
	}

}
